]> dgit.raspbian.org Git - gnome-shell.git/commitdiff
st/image-content: Don't force preferred content size to texture size
authorJonas Dreßler <verdre@v0yd.nl>
Wed, 26 Mar 2025 15:12:19 +0000 (16:12 +0100)
committerMarge Bot <marge-bot@gnome.org>
Mon, 31 Mar 2025 13:20:25 +0000 (13:20 +0000)
When ClutterImage got merged into StImageContent with commit 64d5d01360
("st: Merge ClutterImage with ImageContent"), a small error slipped in when
copying over the update_image_size() function.

Within ClutterImage, update_image_size() served a simple purpose: To call
clutter_content_invalidate_size() in case the texture size would change.
To check that, ClutterImage was storing the existing texture size in the
priv->width and priv->height fields.

When merging into StImageContent, those priv->width/height fields happened
to overlap with priv->width/height of StImageContent, but there they are
storing the preferred size, rather than the texture size. Copying
update_image_size() as-is into StImageContent meant we now set the
preferred size to the texture size, subtly breaking resource-scaled StIcons
(where texture size is a multiple of the preferred size).

The breakage isn't very apparent because StIcons manually set the size
of their internal ClutterActor child to the requested icon-size via
clutter_actor_set_size() in st_texture_cache_load_gicon(), and that makes
the child actor report the correct size in get_preferred_width/height(). The
child actor gets allocated via clutter_actor_allocate_align_fill() from
ClutterBinLayouts vfunc_allocate(), and clutter_actor_allocate_align_fill()
honors both the available size from the parent and the CONTENT_SIZE
request-mode on the child. So when the StIcon has a larger allocation (aka
extra available size), clutter_actor_allocate_align_fill() will fill that
available space with the (too large) content size.

To reproduce the issue, on a resource-scaled monitor, simply create an
StIcon with a fixed width and height that's larger than the icon-size. The
icon will be painted too large and blurry.

Fix this fallout by avoiding to touch the priv->width/height properties on
StImageContent, and instead simply comparing old texture size to new texture
size, we have both textures around after all!

Fixes: 64d5d01360 ("st: Merge ClutterImage with ImageContent")
Closes: https://gitlab.gnome.org/GNOME/gnome-shell/-/issues/8287
Part-of: <https://gitlab.gnome.org/GNOME/gnome-shell/-/merge_requests/3680>

src/st/st-image-content.c

index 8c47af3cd24579aa8393312ad09c8452a8f7954d..9cd0d48f10b645f129b31e1d83e01152ea3f2d4f 100644 (file)
@@ -425,28 +425,6 @@ st_image_content_get_is_symbolic (StImageContent *content)
   return content->is_symbolic;
 }
 
-
-static void
-update_image_size (StImageContent *self)
-{
-  int width, height;
-
-  if (self->texture == NULL)
-    return;
-
-  width = cogl_texture_get_width (self->texture);
-  height = cogl_texture_get_height (self->texture);
-
-  if (self->width == width &&
-      self->height == height)
-    return;
-
-  self->width = width;
-  self->height = height;
-
-  clutter_content_invalidate_size (CLUTTER_CONTENT (self));
-}
-
 /**
  * st_image_content_set_data:
  * @content: a #StImageContentImage
@@ -502,11 +480,19 @@ st_image_content_set_data (StImageContent   *content,
                            guint             row_stride,
                            GError          **error)
 {
+  int old_width = 0;
+  int old_height = 0;
+
   g_return_val_if_fail (ST_IS_IMAGE_CONTENT (content), FALSE);
   g_return_val_if_fail (data != NULL, FALSE);
 
   if (content->texture != NULL)
-    g_object_unref (content->texture);
+    {
+      old_width = cogl_texture_get_width (content->texture);
+      old_height = cogl_texture_get_height (content->texture);
+
+      g_object_unref (content->texture);
+    }
 
   content->texture = cogl_texture_2d_new_from_data (cogl_context,
                                                     width,
@@ -520,7 +506,9 @@ st_image_content_set_data (StImageContent   *content,
     return FALSE;
 
   clutter_content_invalidate (CLUTTER_CONTENT (content));
-  update_image_size (content);
+
+  if (old_width != width || old_height != height)
+    clutter_content_invalidate_size (CLUTTER_CONTENT (content));
 
   return TRUE;
 }
@@ -560,12 +548,19 @@ st_image_content_set_bytes (StImageContent   *content,
                             GError          **error)
 {
 
+  int old_width = 0;
+  int old_height = 0;
+
   g_return_val_if_fail (ST_IS_IMAGE_CONTENT (content), FALSE);
   g_return_val_if_fail (data != NULL, FALSE);
 
-
   if (content->texture != NULL)
-    g_object_unref (content->texture);
+    {
+      old_width = cogl_texture_get_width (content->texture);
+      old_height = cogl_texture_get_height (content->texture);
+
+      g_object_unref (content->texture);
+    }
 
   content->texture = cogl_texture_2d_new_from_data (cogl_context,
                                                     width,
@@ -579,7 +574,9 @@ st_image_content_set_bytes (StImageContent   *content,
     return FALSE;
 
   clutter_content_invalidate (CLUTTER_CONTENT (content));
-  update_image_size (content);
+
+  if (old_width != width || old_height != height)
+    clutter_content_invalidate_size (CLUTTER_CONTENT (content));
 
   return TRUE;
 }